package org.dromara.system.controller.system;

import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.bo.SysDictTypeBo;
import org.dromara.system.domain.vo.SysDictTypeVo;
import org.dromara.system.service.ISysDictTypeService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;


/**
 * @Author 刘武贵
 * @Date 2024/8/15 22:00
 * @Description 功能描述：数据字典信息
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/dict/type")
public class SysDictTypeController extends BaseController {

    /**
     * 字典 业务层（类型）
     */
    private final ISysDictTypeService dictTypeService;

    /**
     * 查询字典类型列表
     *
     * @param dictType 字典类型对象，用于接收查询条件
     * @param pageQuery 分页查询对象，用于接收分页参数
     * @return 返回一个TableDataInfo对象，包含了分页后的字典类型数据和总记录数
     */
    @SaCheckPermission("system:dict:list")
    @GetMapping("/list")
    public TableDataInfo<SysDictTypeVo> list(SysDictTypeBo dictType, PageQuery pageQuery) {
        return dictTypeService.selectPageDictTypeList(dictType, pageQuery);
    }

    /**
     * 导出字典类型列表
     *
     * @param dictType 字典类型对象，包含要导出的字典类型信息
     * @param response 用于响应导出的Excel文件
     */
    @Log(title = "字典类型", businessType = BusinessType.EXPORT)
    @SaCheckPermission("system:dict:export")
    @PostMapping("/export")
    public void export(SysDictTypeBo dictType, HttpServletResponse response) {
        // 查询字典类型列表
        List<SysDictTypeVo> list = dictTypeService.selectDictTypeList(dictType);
        // 导出字典类型列表到Excel文件
        ExcelUtil.exportExcel(list, "字典类型", SysDictTypeVo.class, response);
    }

    /**
     * 查询字典类型详细
     * 通过字典ID获取相应的字典信息，委托给dictTypeService中的selectDictTypeById方法进行数据库查询
     * 使用R对象包装返回结果，表示操作成功并携带查询到的字典信息
     *
     * @param dictId 字典ID
     * @return 返回字典信息的响应对象
     */
    @SaCheckPermission("system:dict:query")
    @GetMapping(value = "/{dictId}")
    public R<SysDictTypeVo> getInfo(@PathVariable Long dictId) {
        return R.ok(dictTypeService.selectDictTypeById(dictId));
    }

    /**
     * 新增字典类型
     * 该方法用于向系统字典中添加新的字典类型，但在添加之前，会先校验字典类型的唯一性，
     * 如果字典类型已存在，则返回失败信息；如果唯一性校验通过，则插入新的字典类型记录，
     * 并返回成功信息
     *
     * @param dict 待添加的字典类型对象，包含字典类型的相关信息
     * @return R<Void> 返回一个结果对象，其中包含操作是否成功的标志及提示信息
     */
    @SaCheckPermission("system:dict:add")
    @Log(title = "字典类型", businessType = BusinessType.INSERT)
    @PostMapping
    public R<Void> add(@Validated @RequestBody SysDictTypeBo dict) {
        // 检查字典类型是否唯一，如果不唯一则返回新增失败的提示信息
        if (!dictTypeService.checkDictTypeUnique(dict)) {
            return R.fail("新增字典'" + dict.getDictName() + "'失败，字典类型已存在");
        }
        dictTypeService.insertDictType(dict);
        return R.ok();
    }

    /**
     * 修改字典类型
     * <p>
     * 该方法用于更新系统字典类型的信息它首先验证请求的字典类型是否唯一，
     * 如果唯一，则通过服务层更新字典类型信息；如果不唯一，则返回失败信息
     * <p>
     * 【注】@Validated 注解用于开启参数校验，确保传入的字典类型对象符合设定的验证规则
     *
     * @param dict 经过验证的字典类型对象，包含修改的字典类型信息
     * @return R<Void> 返回操作结果，成功时返回 R.ok()，失败时返回 R.fail() 并附带错误信息
     */
    @SaCheckPermission("system:dict:edit")
    @Log(title = "字典类型", businessType = BusinessType.UPDATE)
    @PutMapping
    public R<Void> edit(@Validated @RequestBody SysDictTypeBo dict) {
        // 检查字典类型是否唯一，如果不唯一则返回修改失败的提示
        if (!dictTypeService.checkDictTypeUnique(dict)) {
            return R.fail("修改字典'" + dict.getDictName() + "'失败，字典类型已存在");
        }
        dictTypeService.updateDictType(dict);
        return R.ok();
    }

    /**
     * 删除字典类型
     * 该方法通过调用dictTypeService的deleteDictTypeByIds方法，实现批量删除字典类型的功能
     * 利用传入的字典ID数组，来标识需要删除的具体字典类型
     * 成功执行删除操作后，返回一个表示操作成功的响应对象
     *
     * @param dictIds 字典ID串
     * @return 返回结果对象，包含空的返回数据，表示操作成功
     */
    @SaCheckPermission("system:dict:remove")
    @Log(title = "字典类型", businessType = BusinessType.DELETE)
    @DeleteMapping("/{dictIds}")
    public R<Void> remove(@PathVariable Long[] dictIds) {
        dictTypeService.deleteDictTypeByIds(dictIds);
        return R.ok();
    }

    /**
     * 刷新字典缓存
     * 该方法用于重置字典类型缓存，以确保字典数据的最新和一致性
     * 在字典类型或字典数据发生变更后，调用此方法可以更新缓存中的数据，避免缓存击穿或缓存雪崩问题
     *
     * @return 返回响应结果，此处返回Void类型，表示不需要返回具体的业务数据
     */
    @SaCheckPermission("system:dict:remove")
    @Log(title = "字典类型", businessType = BusinessType.CLEAN)
    @DeleteMapping("/refreshCache")
    public R<Void> refreshCache() {
        // 调用字典类型服务的重置缓存方法，具体实现细节在该方法中
        dictTypeService.resetDictCache();
        return R.ok();
    }

    /**
     * 获取字典选择框列表
     * 本方法用于查询所有字典类型的信息，旨在提供一个便捷的方式来获取系统中所有字典类型的列表
     * 它委托字典类型服务（dictTypeService）来执行实际的数据检索操作，然后将结果封装在一个响应对象中返回
     *
     * @return 返回封装了字典类型列表的结果对象，如果查询成功，列表将作为ok响应的data字段返回
     */
    @GetMapping("/optionselect")
    public R<List<SysDictTypeVo>> optionselect() {
        List<SysDictTypeVo> dictTypes = dictTypeService.selectDictTypeAll();
        return R.ok(dictTypes);
    }
}
